# this class provides the action handler
# and all the functions specific to the triggered events 


import pygame, sys, math
from player import *
from pygame.locals import *
from menu import *
from enemy import *
from stage import *
from data import *
from collision import *


class PyrianOne:
     def __init__(self):
          pygame.mixer.pre_init(44100, -16, 2, 2048)
          pygame.init()
          pygame.mixer.set_num_channels(32)
          self.screenx = 1024
          self.screeny = 768
          screenDepth = pygame.display.mode_ok((self.screenx, self.screeny),0,32)
          self.screen = pygame.display.set_mode((self.screenx,self.screeny),0,screenDepth)
          pygame.display.set_caption("PyrianOne")
          pygame.display.flip()
          # initialises a clock object to calculate the FPS
          self.clock = pygame.time.Clock()
          
          self.inGame = False
          self.menu = Menu(self.screen)
          self.inMenu = True
          self.runningGame = False
          self.pause = False
          self.developerMode = False
          
          self.Background = Surface((self.screenx,self.screeny + 50)).convert()
          self.BackgroundOffset = -50
          
          self.GameData = Data()
          self.stage = Stage(1)
          self.player = Player()
          
          pygame.mouse.set_visible(False)

     # in this section all the events like clicking  on  
     # exit or pressing a button are handled.
     # a function is called in which the action happens
     def eventHandler(self):          
          for event in pygame.event.get():
                    if event.type == KEYDOWN:
                         self.keydownEvent(event.key)
                    elif event.type == KEYUP:
                         self.keyupEvent(event.key)
                    elif event.type == MOUSEBUTTONDOWN:
                         self.mousedownEvent(event.button, event.pos)
                    elif event.type == MOUSEBUTTONUP:
                         self.mouseupEvent(event.button, event.pos) 
                    elif event.type == MOUSEMOTION:
                         self.mouseMotionEvent(event.buttons, event.pos, event.rel)
                    elif event.type == QUIT:
                         self.quitGame()               
               
     # this is the main game loop
     # the game is either in menu mode or in game mode
     def mainGame(self):          
          
          while(True):
               
               while self.inMenu:
                    self.menuEventHandler()
                    self.menuDrawUpdate()
                    pygame.display.flip()
                    self.clock.tick(30)

                    
               while self.inGame:
                    self.eventHandler()
                    self.variablesUpdate()
                    self.soundUpdate()
                    self.drawUpdate()
                    pygame.display.flip()
                    
                    #TODO Remove Later
                    pygame.display.set_caption("PyrianOne FPS %i " %self.clock.get_fps())
                    
                    self.clock.tick(30)                    
               
     # an extra event handler for the menu
     def menuEventHandler(self):          
          for event in pygame.event.get():
               if event.type == KEYDOWN:
                    if event.key == K_UP or key == K_w:
                         self.menu.cursorUp()
                    elif event.key == K_DOWN or key == K_s:
                         self.menu.cursorDown()
                    elif event.key == K_ESCAPE:
                         if self.inMenu and not(self.runningGame):
                              self.quitGame()
                         elif self.inMenu and self.runningGame:
                              self.inMenu = False
                              self.inGame = True
                    elif event.key == K_RETURN:
                         self.menuAction()
               elif event.type == QUIT:
                    self.quitGame()
     
     # all entities like the player,enemys, bullets an powerups are drawed    
     def menuDrawUpdate(self):
          self.screen.fill((255, 255, 255))
          pygame.draw.rect(self.screen, (255, 0, 0), (500, 100, 200, 25), 0)
          pygame.draw.rect(self.screen, (255, 0, 0), (500, 150, 200, 25), 0)
          pygame.draw.rect(self.screen, (255, 0, 0), (500, 200, 200, 25), 0)
          pygame.draw.rect(self.screen, (255, 0, 0), (500, 250, 200, 25), 0)
          pygame.draw.rect(self.screen, (255, 0, 0), (500, 300, 200, 25), 0)
          
          if self.menu.selected == 0:
               pygame.draw.rect(self.screen, (255, 100, 100), (500, 100, 200, 25), 0)
          elif self.menu.selected == 1:
               pygame.draw.rect(self.screen, (255, 100, 100), (500, 150, 200, 25), 0)
          elif self.menu.selected == 2:
               pygame.draw.rect(self.screen, (255, 100, 100), (500, 200, 200, 25), 0)
          elif self.menu.selected == 3: 
               pygame.draw.rect(self.screen, (255, 100, 100), (500, 250, 200, 25), 0)
          elif self.menu.selected == 4:
               pygame.draw.rect(self.screen, (255, 100, 100), (500, 300, 200, 25), 0)
     
     # what happens when selection a specific menu entry
     def menuAction(self):
          if self.menu.selected == 0:
               self.inMenu = False
               self.inGame = True
               self.player.isInStage = 1
               self.player.reset()
               self.stage = Stage(1)
               self.GameData.BackgroundMusicStage1.play(-1)
                    
          elif self.menu.selected == 1:
               print "load a game"               
          elif self.menu.selected == 2:
               print "go to the options"
          elif self.menu.selected == 3: 
               print "goto the about sectiont"
          elif self.menu.selected == 4:
               self.quitGame() 
               
     # update all variables like positions life etc..
     def variablesUpdate(self):
          # updates the player position an the bullets he shots
          self.player.move()
          self.player.fire()
          for bullet in self.player.bulletArray:
               if bullet.posy == bullet.targety:
                    self.player.bulletArray.remove(bullet)
               bullet.move()
          
          # update the stage
          self.stage.update()
          
          # check if enemy's have to disappear
          enemys = dict(self.stage.enemyDict)
          
          for enemy in enemys.iteritems():
               if enemy[1].alive == False and abs(enemy[1].posx - enemy[1].targetx) < 10 and abs(enemy[1].posy - enemy[1].targety) < 10 : 
                    del self.stage.enemyDict[enemy[0]]
                    
          # check for collision between player an enemys          
          enemys = dict(self.stage.enemyDict)
          
          for enemy in enemys.iteritems():
               if collision_rect(self.player, enemy[1]):
                    
                    playermedianx = self.player.posx + self.player.width/2
                    playermediany = self.player.posy + self.player.height/2
                    
                    enemymedianx = enemy[1].posx + enemy[1].width/2
                    enemymediany = enemy[1].posy + enemy[1].height/2
                    
                    directionx = playermedianx - enemymedianx
                    directiony = playermediany - enemymediany
                    
                    self.player.posx += math.copysign(10, directionx)
                    self.player.posy += math.copysign(10, directiony)
                    
                    self.player.life -= 15
                    enemy[1].life -= 25
                    
                    if enemy[1].life < 1:
                              del self.stage.enemyDict[enemy[0]]           
                   
          # check for collision between playerBullets and enemys
          enemys = dict(self.stage.enemyDict)
          
          for bullet in self.player.bulletArray:
               for enemy in enemys.iteritems():
                    if collision_rect(bullet,enemy[1]):
                         enemy[1].deal_dmg(bullet.dmg)
                         self.GameData.EnemyHit.play()
                         if enemy[1].life < 1:
                              del self.stage.enemyDict[enemy[0]]
                              self.GameData.EnemyExplosion.play()
                         
                         self.player.bulletArray.remove(bullet)
     
          # this variables cause the moving background
          if self.BackgroundOffset < 0:
               self.BackgroundOffset += 2 
          else:
               self.BackgroundOffset = -50
               
          # check if enemy's have to disappear
          
     # everything needs to be drawn on the screen
     def drawUpdate(self):
          
          #draw the backgroud
          for x in range((self.screenx)/self.GameData.BackgroundGrass.get_width()+1):
               for y in range((self.screeny/self.GameData.BackgroundGrass.get_height())+2):
                    self.Background.blit(self.GameData.BackgroundGrass,(x*self.GameData.BackgroundGrass.get_width(),
                                                                    y*self.GameData.BackgroundGrass.get_height()))         
          
          self.screen.blit(self.Background, (0, self.BackgroundOffset))
          
          # draw the player
          if self.developerMode:
               pygame.draw.rect(self.screen, (255, 150, 150), (self.player.posx, self.player.posy,40,52), 1)
          self.screen.blit(self.GameData.PlayerTopImage ,(self.player.posx,self.player.posy))
          
          # draw the bullets
          for bullet in self.player.bulletArray:
               if self.developerMode:
                    pygame.draw.rect(self.screen, (255, 0, 0), (bullet.posx, bullet.posy,8,22), 1)
               self.screen.blit(self.GameData.PlayerShotOne,(bullet.posx, bullet.posy))
               
          # draw all the enemys
          for enemy in self.stage.enemyDict.iteritems():
               if self.developerMode:
                    pygame.draw.rect(self.screen, (234, 124, 53), (enemy[1].posx, enemy[1].posy,32,52), 1)
               self.screen.blit(self.GameData.EnemyOne,(enemy[1].posx, enemy[1].posy))
          
          # Draw the HUD
          
          
     # play all the sounds! Yeah!
     def soundUpdate(self):
          if pygame.key.get_pressed()[K_SPACE] == 1 and self.GameData.PlayerShotOneSoundDelay == 0:
               self.GameData.PlayerShotOneSound.play()
               self.GameData.PlayerShotOneSoundDelay = 3
               
          elif self.GameData.PlayerShotOneSoundDelay > 0:
               self.GameData.PlayerShotOneSoundDelay -= 1
          
     # actions when pressing a key down    
     def keydownEvent(self, key):
          # TODO switch to dictionary!
          if key == K_ESCAPE:
               self.inMenu = True
               self.inGame = False
               self.runningGame = True
          elif key == K_w or key == K_UP:
               self.player.w = True          
          elif key == K_a or key == K_LEFT:
               self.player.a = True          
          elif key == K_s or key == K_DOWN:
               self.player.s = True          
          elif key == K_d or key == K_RIGHT:
               self.player.d = True
          elif key == K_SPACE or key == K_j:
               self.player.fireWeapon = True
          elif key == K_LSHIFT or key == K_i:
               self.player.preciseMode = True
          elif key == K_p:
               self.pause = True
               self.GameData.BackgroundMusicStage1.set_volume(0.25)
               #TODO blit a pause image an set more key events so exit the pause screen
               while self.pause:                
                    for event in pygame.event.get():
                         if event.type == KEYDOWN:                             
                              if event.key == 112:
                                   self.pause = False
                                   self.GameData.BackgroundMusicStage1.set_volume(1)
          
          elif key == K_F12:
               if self.developerMode == False:
                    self.developerMode = True
               elif self.developerMode == True:
                    self.developerMode = False       
          
          elif key == K_RCTRL or K_k:
               if self.player.amountBombs > 0:
                    print "boom"
                    self.player.amountBombs -= 1
                    #TODO for enemys in enemyArray:
                         # destroy 'em           
     
     # actions when releasing a key
     def keyupEvent(self, key):
          if key == K_w or key == K_UP:
               self.player.w = False          
          elif key == K_a or key == K_LEFT:
               self.player.a = False          
          elif key == K_s or key == K_DOWN:
               self.player.s = False          
          elif key == K_d or key == K_RIGHT:
               self.player.d = False
          elif key == K_SPACE or key == K_j:
               self.player.fireWeapon = False
          elif key == K_LSHIFT or key == K_i:
               self.player.preciseMode = False
               
               
     def mouseupEvent(self, button, pos):
          pass
     
     def mousedownEvent(self, button, pos):
          pass
     
     def mouseMotionEvent(self, buttons, pos, rel):
          pass
     
     # define what happens when the game is closed
     def quitGame(self):
          pygame.quit()
          sys.exit()

# creations of the game instance
a = PyrianOne()
a.mainGame()
